源码|什么是服务提供者框架?举例?

服务提供者框架中有四个重要的组件:

  • 服务接口(Service Interface):由服务提供者实现,用来抽象服务提供者提供的服务。
  • 提供者注册API(Provider Registration API):系统用来注册实现,让客户端访问它们的。
  • 服务访问API(Service Access API):客户端用来获取服务的实例。
  • 服务提供者接口(Service Provider Interface):可选,由服务提供者实现,用来抽象服务提供者。

JDBC的实现就是一个服务者提供框架应用的典型例子。

JDK版本:oracle java 1.8.0_102

JDBC与服务者提供框架

JDBC中的各角色

JDBC的实现中包含有服务提供者接口,具体如下:

  • 服务接口:Connection
  • 服务提供者接口:Driver
  • 提供者注册API:DriverManager.registerDriver()方法
  • 服务访问API:DriverManager.getConnection()方法

具体实现

服务接口:Connection

Connection即为数据库连接服务,没什么特殊的,注意接口的多继承:

1
2
3
public interface Connection extends Wrapper, AutoCloseable {
}

服务提供者接口:Driver

Driver生成Connection服务:

1
2
3
4
5
6
public interface Driver {
Connection connect(String url, java.util.Properties info)
throws SQLException;
}

记住Driver#connect()方法,后面还会见到。

提供者注册API:DriverManager.registerDriver()方法

服务的提供者实现Driver类,通过DriverManager.registerDriver()将服务提供者的实例注册到DriverManager中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class DriverManager {
public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
registerDriver(driver, null);
}
public static synchronized void registerDriver(java.sql.Driver driver,
DriverAction da)
throws SQLException {
/* Register the driver if it has not already been added to our list */
if(driver != null) {
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
// This is for compatibility with the original DriverManager
throw new NullPointerException();
}
println("registerDriver: " + driver);
}
}

具体的注册行为由服务提供者发起。MySQL的Driver实现com.mysql.jdbc.Driver为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
}

可知,在第一次加载com.mysql.jdbc.Driver时,com.mysql.jdbc.Driver会利用静态代码块调用提供者注册API DriverManager.registerDriver()。

服务访问API:DriverManager.getConnection()方法

注册服务提供者的实例后,服务提供者就能够通过框架提供服务。具体来说,可通过静态工厂方法DriverManager.getConnection()提供Connection服务,底层是通过Driver接口的实现类实现的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class DriverManager {
public static Connection getConnection(String url)
throws SQLException {
java.util.Properties info = new java.util.Properties();
return (getConnection(url, info, Reflection.getCallerClass()));
}
// Worker method called by the public getConnection() methods.
private static Connection getConnection(
for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + aDriver.getClass().getName());
}
}
}
}

注意这里的命名方式getConnection,目前的实现中,每次返回的是新的Connection实例,感觉叫做newConnection更恰当。不知道为什么这样命名。

这里的逻辑很简单,遍历所有已注册的Driver实现类,选择第一个可用的Driver创建Connection。还记得Driver#connect()方法吗?aDriver.driver.connect一句中,由底层Driver完成Connection的创建

done

扫描微信关注我
微信公众号二维码
本文链接:源码|什么是服务提供者框架?举例?
作者:猴子007
出处:https://monkeysayhi.github.io
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名及链接。
我是猴子007,<br>一只非常特殊的动物,<br>可以从事程序的开发、维护,<br>经常因寻找香蕉或母猿而无心工作。